﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace SchoolDomain
{
    /// <summary>
    /// Класс для представления оценки.
    /// </summary>
    public class Mark : INotifyPropertyChanged
    {
        #region Константы
        /// <summary>
        /// Начальный рейтинг.
        /// </summary>
        public const int START_RATING = 60;
        /// <summary>
        /// Изменение рейтинга за один пропуск.
        /// </summary>
        public const int ABSENCE_RATING = -2;
        /// <summary>
        /// Изменение рейтинга за одно опоздание.
        /// </summary>
        public const int BEING_LATE_RATING = -3;
        /// <summary>
        /// Изменение рейтинга за одну творческую активность.
        /// </summary>
        public const int CREATIVE_ACTIVITY_RATING = 4;
        /// <summary>
        /// Изменение рейтинга за один деструктивный конфликт.
        /// </summary>
        public const int DESTRUCTIVE_CONFLICT_RATING = -4;
        /// <summary>
        /// Изменение рейтинга за одно дисциплинарное замечание.
        /// </summary>
        public const int DISCIPLINE_NOTE_RATING = -2;
        #endregion

        #region Поля и свойства
        /// <summary>
        /// Генератор случайных чисел.
        /// </summary>
        private static Random random = new Random();

        /// <summary>
        /// ИД оценки.
        /// </summary>
        private Guid id;
        /// <summary>
        /// ИД оценки.
        /// </summary>
        public virtual Guid Id
        {
            get { return id; }
            set
            {
                id = value;
                OnPropertyChanged("Id");
            }
        }

        /// <summary>
        /// Обычная оценка.
        /// </summary>
        private int? standardMark;
        /// <summary>
        /// Обычная оценка.
        /// </summary>
        public virtual int? StandardMark
        {
            get { return standardMark; }
            set
            {
                standardMark = value;
                OnPropertyChanged("StandardMark");
            }
        }

        /// <summary>
        /// Пропуск.
        /// </summary>
        private bool absence;
        /// <summary>
        /// Пропуск.
        /// </summary>
        public virtual bool Absence
        {
            get { return absence; }
            set
            {
                absence = value;
                OnPropertyChanged("Absence");
            }
        }

        /// <summary>
        /// Опоздание.
        /// </summary>
        private bool beingLate;
        /// <summary>
        /// Опоздание.
        /// </summary>
        public virtual bool BeingLate
        {
            get { return beingLate; }
            set
            {
                beingLate = value;
                OnPropertyChanged("BeingLate");
            }
        }

        /// <summary>
        /// Творческая активность.
        /// </summary>
        private bool creativeActivity;
        /// <summary>
        /// Творческая активность.
        /// </summary>
        public virtual bool CreativeActivity
        {
            get { return creativeActivity; }
            set
            {
                creativeActivity = value;
                OnPropertyChanged("CreativeActivity");
            }
        }

        /// <summary>
        /// Деструктивный конфликт.
        /// </summary>
        private bool destructiveConflict;
        /// <summary>
        /// Деструктивный конфликт.
        /// </summary>
        public virtual bool DestructiveConflict
        {
            get { return destructiveConflict; }
            set
            {
                destructiveConflict = value;
                OnPropertyChanged("DestructiveConflict");
            }
        }

        /// <summary>
        /// Дисциплинарное замечание.
        /// </summary>
        private bool disciplineNote;
        /// <summary>
        /// Дисциплинарное замечание.
        /// </summary>
        public virtual bool DisciplineNote
        {
            get { return disciplineNote; }
            set
            {
                disciplineNote = value;
                OnPropertyChanged("DisciplineNote");
            }
        }

        /// <summary>
        /// Ученик, которому поставлена оценка.
        /// </summary>
        private Student student;
        /// <summary>
        /// Ученик, которому поставлена оценка.
        /// </summary>
        public virtual Student Student
        {
            get { return student; }
            set
            {
                student = value;
                OnPropertyChanged("Student");
            }
        }

        /// <summary>
        /// Урок, в который поставлена оценка.
        /// </summary>
        private Unit unit;
        /// <summary>
        /// Урок, в который поставлена оценка.
        /// </summary>
        public virtual Unit Unit
        {
            get { return unit; }
            set
            {
                unit = value;
                OnPropertyChanged("Unit");
            }
        }
        #endregion

        /// <summary>
        /// Вычислить рейтинг учебной успешности, соответствующий оценке.
        /// </summary>
        /// <returns>рейтинг учебной успешности</returns>
        public virtual int GetRating()
        {
            int result = 0;
            if (absence)
                result += ABSENCE_RATING;
            if (beingLate)
                result += BEING_LATE_RATING;
            if (creativeActivity)
                result += CREATIVE_ACTIVITY_RATING;
            if (destructiveConflict)
                result += DESTRUCTIVE_CONFLICT_RATING;
            if (disciplineNote)
                result += DISCIPLINE_NOTE_RATING;
            return result;
        }

        /// <summary>
        /// Получить корректировку среднего балла по рейтингу.
        /// </summary>
        /// <param name="rating">рейтинг учебной успешности</param>
        public static double GetRatingEffect(int rating)
        {
            if (rating < 46)
                return -0.5;
            if (rating < 50)
                return -0.3;
            if (rating < 54)
                return -0.2;
            if (rating < 59)
                return -0.1;
            if (rating < 65)
                return 0.0;
            if (rating < 81)
                return 0.1;
            if (rating < 87)
                return 0.2;
            if (rating < 92)
                return 0.3;
            if (rating < 96)
                return 0.4;
            return 0.5;
        }

        /// <summary> 
        /// Проверить, что оценка эквивалентна пустой.
        /// </summary>
        /// <returns>истина, если оценка пуста</returns>
        public virtual bool IsEmpty()
        {
            return (standardMark == null) && !absence && !beingLate && !creativeActivity &&
                !destructiveConflict && !disciplineNote;
        }

        #region INotifyPropertyChanged Members
        
        /// <summary>
        /// Событие на изменение значения свойства.
        /// </summary>
        public virtual event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Генерация события на изменение значения свойства.
        /// </summary>
        /// <param name="propertyName">имя свойства</param>
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

    /// <summary>
    /// Класс, представляющий ученика.
    /// </summary>
    public class Student: INotifyPropertyChanged
    {
        #region Поля и свойства
        /// <summary>
        /// ИД ученика.
        /// </summary>
        private Guid id;
        /// <summary>
        /// ИД ученика.
        /// </summary>
        public virtual Guid Id
        {
            get { return id; }
            set
            {
                id = value;
                OnPropertyChanged("Id");
            }
        }
        /// <summary>
        /// Фамилия ученика.
        /// </summary>
        private string name;
        /// <summary>
        /// Фамилия ученика.
        /// </summary>
        public virtual string Name
        {
            get { return name; }
            set
            {
                name = value;
                OnPropertyChanged("Name");
            }
        }
        #endregion

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Событие на изменение значения свойства.
        /// </summary>
        public virtual event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Генерация события на изменение значения свойства.
        /// </summary>
        /// <param name="propertyName">имя свойства</param>
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

    /// <summary>
    /// Класс, представляющий урок.
    /// </summary>
    public class Unit: INotifyPropertyChanged
    {
        #region Поля и свойства
        /// <summary>
        /// ИД урока.
        /// </summary>
        private Guid id;
        /// <summary>
        /// ИД урока.
        /// </summary>
        public virtual Guid Id
        {
            get { return id; }
            set
            {
                id = value;
                OnPropertyChanged("Id");
            }
        }
        /// <summary>
        /// Дата проведения урока.
        /// </summary>
        private DateTime unitDate;
        /// <summary>
        /// Дата проведения урока.
        /// </summary>
        public virtual DateTime UnitDate
        {
            get { return unitDate; }
            set
            {
                unitDate = value;
                OnPropertyChanged("UnitDate");
            }
        }

        /// <summary>
        /// Коллекция оценок за урок.
        /// </summary>
        private IList<Mark> marks;
        /// <summary>
        /// Коллекция оценок за урок.
        /// </summary>
        public virtual IList<Mark> Marks
        {
            get { return marks; }
            set { marks = value; }
        }
        #endregion

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Событие на изменение значения свойства.
        /// </summary>
        public virtual event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Генерация события на изменение значения свойства.
        /// </summary>
        /// <param name="propertyName">имя свойства</param>
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

}
